﻿using H.Eyes;
using H.Types;
using H.Utils.DataStruct;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace H.DML.See
{
    public class DMImgSee : ISee
    {
        /// <summary>
        /// 大漠实例
        /// </summary>
        protected readonly DMEye _Dml;

        /// <summary>
        /// 内部存储查找参数
        /// </summary>
        protected readonly DMOption _Option;

        ///<inheritdoc/>
        public IEnumerable<string> ObjNames { get; }

        /// <summary>
        /// 当前ImgSeeable表示的图片
        /// </summary>
        private readonly string PicInfos;

        /// <summary>
        /// 每一张图片的基准点偏移
        /// </summary>
        protected readonly Pos[] _BaseOffsets;

        /// <summary>
        /// 存储图片的内存块
        /// </summary>
        private readonly MemBlock _MemBlock;

        /// <summary>
        /// 初始化一个找图实例
        /// </summary>
        /// <param name="seeable"></param>
        public DMImgSee(DMEye dml, IImgEntity[] imgs, DMOption option)
        {
            _Dml = dml;

            //处理图片信息
            int count = imgs.Length;
            string[] names = new string[count];
            Pos[] offsets = new Pos[count];
            int size = 0;
            foreach (IImgEntity img in imgs)
            {
                size += img.Bin.Length;
            }
            MemBlock memBlock = new MemBlock();
            IntPtr ptr = memBlock.EnsureSize(size);
            string[] picInfo = new string[count];

            for (int i = 0; i < count; i++)
            {
                IImgEntity entity = imgs[i];
                names[i] = entity.Name;
                offsets[i] = entity.BaseOffset;
                Marshal.Copy(entity.Bin, 0, ptr, entity.Bin.Length);
                picInfo[i] = $"{ptr.ToInt32()},{entity.Bin.Length}";
                ptr += entity.Bin.Length;
            }
            ObjNames = names;
            _BaseOffsets = offsets;
            _MemBlock = memBlock;
            PicInfos = string.Join("|", picInfo);

            _Option = option;
        }



        /// <inheritdoc/>
        public bool See(Rect matchRect)
        {
            if (matchRect.Left >= matchRect.Right || matchRect.Top >= matchRect.Bottom)
            {
                return false;
            }
            return _Dml.FindPicMem(matchRect, PicInfos, _Option?.DeletaColor.StrRGB ?? "000000", 1.0, 0, out _) != -1;
        }

        /// <inheritdoc/>
        public virtual int See(Rect matchRect, out Pos matchPoint)
        {
            if (matchRect.Left >= matchRect.Right || matchRect.Top >= matchRect.Bottom)
            {
                matchPoint = Pos.Empty;
                return -1;
            }
            return _Dml.FindPicMem(matchRect, PicInfos, _Option?.DeletaColor.StrRGB ?? "000000", 1.0, 0, out matchPoint);
        }


        /// <inheritdoc/>
        public virtual int[] See(Rect matchRect, out Pos[] matchPoints)
        {
            if (matchRect.Left >= matchRect.Right || matchRect.Top >= matchRect.Bottom)
            {
                matchPoints = null;
                return null;
            }
            string ret = _Dml.FindPicMemEx(matchRect, PicInfos, _Option?.DeletaColor.StrRGB ?? "000000", 1.0, 0);
            if (string.IsNullOrEmpty(ret))
            {
                matchPoints = null;
                return null;
            }
            else
            {
                string[] pieces = ret.Split(',', '|');
                int count = pieces.Length / 3;
                matchPoints = new Pos[count];
                int[] returns = new int[count];
                for (int i = 0; i < pieces.Length; i += 3)
                {
                    matchPoints[i / 3] = new Pos(int.Parse(pieces[i + 1]), int.Parse(pieces[i + 2]));
                    returns[i / 3] = int.Parse(pieces[i]);
                }
                return returns;
            }
        }

        /// <summary>
        /// 匹配到的左上角的坐标点
        /// </summary>
        /// <param name="matchPoints">所有匹配的坐标点</param>
        /// <param name="indexs">所有坐标点对应的序号,用于查找对应的图片</param>
        protected void AddOffset(Pos[] matchPoints, int[] indexs)
        {
            int count = matchPoints.Length;
            if (indexs.Length != count)
            {
                throw new IndexOutOfRangeException($"参数{nameof(matchPoints)}与{nameof(indexs)}的数量不一致");
            }
            for (int i = 0; i < count; i++)
            {
                matchPoints[i].Offset(_BaseOffsets[indexs[i]]);
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _MemBlock.Dispose();
            }

        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        ~DMImgSee()
        {
            Dispose(false);
        }

    }
}
